//Include General
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h> 
#include <sys/ioctl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <termios.h> 
#include <pthread.h>

//Include Specific
#include "drv_uart.h"

// on init les thread de reception 
static void drv_uartInitThread ( drv_uartCallbackHandler cb );
//Thread de reception .
static void* drv_uartReceptThread(void* cb);

//file descriptor
static int fd_uart =-1;				


//Initialize configuration of Uart bridge
int drv_uartOpen ( char* tty, drv_uartCallbackHandler cb )
{
	struct termios termios_p;
	
	//on ouvre le port usb
	if ( (fd_uart = open( tty , O_RDWR | O_NOCTTY /*| O_NONBLOCK*/ )) == -1 ) 
	{
		printf("erreur port\n");
		exit(-1);
	}
	
	//lecture des parametres courants
	tcgetattr(fd_uart, &termios_p);
	bzero(&termios_p,sizeof(termios_p));
	
	//modification des parametres
	termios_p.c_cflag = B115200 | CS8 | CREAD | CLOCAL;
	termios_p.c_iflag = IGNPAR;
	termios_p.c_oflag = 0;
	termios_p.c_lflag = ICANON ;
	termios_p.c_cc[VMIN] = 1;
	termios_p.c_cc[VTIME] = 0;

	//sauvegarde des nouveaux parametres
	tcflush(fd_uart,TCIFLUSH);
	tcsetattr(fd_uart,TCSANOW,&termios_p);
	
	//on init le thread
	drv_uartInitThread ( cb );
	
	return fd_uart;
}

//write
int drv_uartWriteBytes( char * buffer )
{
	return write(fd_uart, buffer, strlen(buffer) );
}

//close
void drv_uartClose ( int fd_uart  )
{
	printf("close uart \n");
	close( fd_uart );  
}

//Initialize le thread de reception.			                              
static void drv_uartInitThread ( drv_uartCallbackHandler cb )
{	
	pthread_t threard_recept;

	//on init le thread
	pthread_create (&threard_recept, NULL, drv_uartReceptThread, (void *)cb ) ;	
}

//Thread de reception
static void* drv_uartReceptThread(void* cb)
{
	char buf[ 255 ]; 

	drv_uartCallbackHandler m_cb = (drv_uartCallbackHandler )cb;
	while( 1 )
	{
		int nb_bytes_to_read = read( fd_uart , buf, 255 );	
		if( nb_bytes_to_read > 0)
		{
			S_Gpgga gpgga_frame;
			
			if( strncmp (buf,"$GPGGA",5) == 0 )
			{
				buf[ nb_bytes_to_read ] = '\0';
				//printf( "buf => %s\n" , buf );
				int index_start = 7;
				int index_stop = 0;
				char *split_str;
				//time
				memset(gpgga_frame.time , '\0' , 15);
				split_str = strchr( &buf[ index_start  ], ',' );
				index_stop = split_str-&buf[ index_start  ];
				strncpy(gpgga_frame.time , &buf[ index_start ] , index_stop);

				//latitude
				memset(gpgga_frame.latitude , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
				strncpy(gpgga_frame.latitude , &buf[ index_start ] , index_stop);

				//latitude
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
		  		strncat(gpgga_frame.latitude, &buf[ index_start ] , index_stop);

				//longitude
				memset(gpgga_frame.longitude , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
				strncpy(gpgga_frame.longitude , &buf[ index_start ] , index_stop);

				//longitude
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
		  		strncat(gpgga_frame.longitude, &buf[ index_start ] , index_stop);

				//quality
				memset(gpgga_frame.quality , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
				strncpy(gpgga_frame.quality , &buf[ index_start ] , index_stop);

				//nb_satellites
				memset(gpgga_frame.nb_satellites , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
				strncpy(gpgga_frame.nb_satellites , &buf[ index_start ] , index_stop);

				//hdop
				memset(gpgga_frame.hdop , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
				strncpy(gpgga_frame.hdop , &buf[ index_start ] , index_stop);

				//altitude
				memset(gpgga_frame.altitude , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
				strncpy(gpgga_frame.altitude , &buf[ index_start ] , index_stop);

				//altitude
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
		  		strncat(gpgga_frame.altitude, &buf[ index_start ] , index_stop);

				//geoidal
				memset(gpgga_frame.geoidal , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
				strncpy(gpgga_frame.geoidal , &buf[ index_start ] , index_stop);

				//geoidal
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
		  		strncat(gpgga_frame.geoidal, &buf[ index_start ] , index_stop);

				//last_update
				memset(gpgga_frame.last_update , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], ',' );
				index_stop = split_str-&buf[ index_start ];
		  		strncpy(gpgga_frame.last_update, &buf[ index_start ] , index_stop);

				//station_id 
				memset(gpgga_frame.station_id , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], '*' );
				index_stop = split_str-&buf[ index_start ];
		  		strncpy(gpgga_frame.last_update, &buf[ index_start ] , index_stop);

				//check_sum 
				memset(gpgga_frame.check_sum  , '\0' , 15);
				index_start = index_start + index_stop + 1;
				split_str = strchr( &buf[ index_start ], '\0' );
				index_stop = split_str-&buf[ index_start ];
		  		strncpy(gpgga_frame.check_sum , &buf[ index_start ] , index_stop);
				
				//send to callback
				m_cb(&gpgga_frame);
		
			}
			else if( strncmp (buf,"$GPGSA",5) == 0 )
			{
				//strncpy ( input_buf, buf, strlen(buf) );
				//printf("$GPGSA => %d => %s\n",input_buf);
			}
			else if( strncmp (buf,"$GPVTG",5) == 0 )
			{
				//strncpy ( input_buf, buf, strlen(buf) );
				//printf("$GPVTG => %d => %s\n",input_buf);
			}
			else if( strncmp (buf,"$GPRMC",5) == 0 )
			{
				//strncpy ( input_buf, buf, strlen(buf) );
				//printf("$GPRMC => %d => %s\n",input_buf);
			}
		}
	}
	return 0;
}









